package com.reebake.ideal.servlet.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.http.Header;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 常用Web工具
 */
@Slf4j
public class WebUtil implements ApplicationContextAware {

	public static final String XML_HTTP_REQUEST_HEADER_NAME = "X-Requested-With";

	private static ObjectMapper objectMapper;

	/**
	 * 判断请求是否为ajax请求
	 * @param request 请求
	 * @return true 是 false 否
	 */
	public static boolean isAjaxRequest(HttpServletRequest request) {
		return StrUtil.isNotBlank(request.getHeader(XML_HTTP_REQUEST_HEADER_NAME))
				|| (StrUtil.isNotBlank(request.getHeader(Header.ACCEPT.getValue()))
				&& request.getHeader(Header.ACCEPT.getValue()).contains(MediaType.APPLICATION_JSON_VALUE))
				|| (StrUtil.isNotBlank(request.getHeader(Header.CONTENT_TYPE.getValue()))
						&& request.getHeader(Header.CONTENT_TYPE.getValue()).contains(MediaType.APPLICATION_JSON_VALUE))
				;
	}

	/**
	 * 判断请求是否为事件流
	 * @param request 请求
	 * @return true 是 false 否
	 */
	public static boolean isEventStreamRequest(HttpServletRequest request) {
		return (StrUtil.isNotBlank(request.getHeader(Header.ACCEPT.getValue()))
				&& request.getHeader(Header.ACCEPT.getValue()).contains(MediaType.TEXT_EVENT_STREAM_VALUE))
				|| (StrUtil.isNotBlank(request.getHeader(Header.CONTENT_TYPE.getValue()))
				&& request.getHeader(Header.CONTENT_TYPE.getValue()).contains(MediaType.TEXT_EVENT_STREAM_VALUE))
				;
	}

	/**
	 * 向输出写入数据
	 * @param response 输出
	 * @param data 未序列化数据对象
	 */
	@SneakyThrows
	public static void writeJson(HttpServletResponse response, Object data) {
		response.setCharacterEncoding(CharsetUtil.UTF_8);
		response.setContentType(MediaType.APPLICATION_JSON.toString());
		if (ObjectUtil.isNull(data)) {
			return;
		}
		response.getWriter().write(objectMapper.writeValueAsString(data));
	}

	/**
	 * 读取请求字符串
	 * @param request 请求
	 * @return 请求体字符串
	 */
	@SneakyThrows
	public static String getRequestBodyAsString(HttpServletRequest request) {
		return IoUtil.read(request.getInputStream(), CharsetUtil.CHARSET_UTF_8);
	}

	/**
	 * 获取请求，没有则报异常
	 * @return 请求
	 */
	public static HttpServletRequest getRequest() {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            return attributes.getRequest();
        }
        throw new RuntimeException("could not find the request in then context.");
	}

	/**
	 * 获取请求的IP地址
	 * @return IP地址
	 */
    public static String getClientIP() {
        return JakartaServletUtil.getClientIP(getRequest());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        WebUtil.objectMapper = applicationContext.getBean(ObjectMapper.class);
	}
}
